﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Security.Cryptography;
using System.Text;

namespace Share.Services;

public class RSACipherService(ILogger<RSACipherService> logger, IOptions<ApiSetting> options) : ICipherService
{
    ApiSetting setting = options.Value;
    //private readonly string publicKey = options.Value.PublicKey;
    //private readonly string privateKey = options.Value.PrivateKey;
    public byte[] Encrypt(byte[] data)
    {
        throw new NotImplementedException();
    }

    public string Sign(string plaintext)
    {
        byte[] data = Encoding.UTF8.GetBytes(plaintext);

        using (var rsa = RSA.Create())
        {
            try
            {
                rsa.ImportFromPem(ToPemFormat(setting.PrivateKey));

                // 使用SHA256哈希算法进行签名
                var result = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                return Convert.ToBase64String(result);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "签名失败");
                return string.Empty;
            }
        }
    }

    public bool Verify(string plaintext, string sign)
    {
        try
        {
            byte[] data = Encoding.UTF8.GetBytes(plaintext);
            byte[] signature = Convert.FromBase64String(sign);

            // 将公钥转换为PEM格式
            string publicKeyPem = ToPemFormat(setting.GatewayPublicKey, pri: false);

            using (var rsa = RSA.Create())
            {
                // 从PEM格式导入公钥
                rsa.ImportFromPem(publicKeyPem);

                // 使用SHA1哈希算法验证签名
                return rsa.VerifyData(data, signature, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
            }
        }
        catch (Exception ex)
        {
            logger.LogError("验签失败,{message}", ex.Message);
            return false;
        }
    }

    public (string, string) KeyGen()
    {
        throw new NotImplementedException();
    }

    /// <summary>
    /// 将 Base64 的密钥转换为 Pem 格式
    /// </summary>
    /// <param name="key"></param>
    /// <param name="pri"></param>
    /// <returns>Pem 格式的密钥字符器</returns>
    /// <remarks>
    /// 坑点：使用 java sdk 生成的密钥对不包含 begin 头尾
    /// 但是使用 c# sdk 生成是包含的
    /// </remarks>
    private string ToPemFormat(string key, bool pri = true)
    {
        // 如果已经是pem格式的key则直接返回
        if (key.StartsWith("-----BEGIN")) return key;

        // 根据pri判断是公钥还是私钥，补充pem格式头尾
        return pri ?
            "-----BEGIN PRIVATE KEY-----" + key + "-----END PRIVATE KEY-----"
            : "-----BEGIN PUBLIC KEY-----" + key + "-----END PUBLIC KEY-----";
    }


}